<template>
	<view class="recorder" @click="showPicker">
		<slot></slot>
		<u-overlay v-show="isShow" style="width: 100% !important" :show="isShow">
			<view class="" style="position: relative; top: 150upx; left: 230upx" v-if="beginRecoding"><image style="width: 300upx" src="../static/yy.gif" mode="widthFix"></image></view>
			<view class="lyview">
				<view class="lyviewTop">
					<view class="lyviewTopLeft" @tap="toclose">取消</view>
					<view class="lyviewTopRight" @tap="touchend2">确定</view>
				</view>

				<view class="lyviewCenter">
					<view class="lyviewCenterTop" @tap="ontap"><image src="../static/ly.png" mode=""></image></view>
					<view class="lyviewCenterCenter">{{ nowDuration }}</view>
					<view class="lyviewCenterBottom">{{ beginRecoding ? '正在录音' : '点击开始录音' }}</view>
				</view>
			</view>
		</u-overlay>
	</view>
</template>
<script>
import Recorder from 'js-audio-recorder';
/**
 * @param isShow 是否显示音频录入组件
 * @param closeAudio 关闭音频录入组件或录音完毕的事件
 */
export default {
	data() {
		return {
			isShow: false,
			beginRecoding: false, // 开始录音
			blackBoxSpeak: false, // 是否上滑取消
			startY: '', // 手指滑动开始Y轴坐标
			timeOutEvent: 0, // 定时器
			waveCanvas: null,
			ctx: null,
			recorder: null, // 音频录入的实例
			drawRecordId: null, // 音频绘画波动图时的音频id
			nowDuration: '0:00', // 当前时长
			limitDuration: 60, // 限制时长，单位-秒
			drawColuList: [] // 录音时的柱状波动图，数据集合
		};
	},
	mounted() {
		// 创建录音实例
		this.recorder = new Recorder({
			sampleBits: 16, // 采样位数，支持 8 或 16，默认是16
			sampleRate: 48000, // 采样率，支持 11025、16000、22050、24000、44100、48000，根据浏览器默认值
			numChannels: 1 // 声道，支持 1 或 2， 默认是1
			// compiling: false,(0.x版本中生效,1.x增加中)  // 是否边录边转换，默认是false
		});
		// 监听录音变化
		const vm = this;
		this.recorder.onprogress = function (params) {
			if (Math.floor(params.duration) === this.limitDuration) {
				vm.touchend();
			}
			let d = Math.floor(params.duration);
			d = Number(d) < 10 ? '0' + d : d;
			d = '0:' + d;
			vm.$set(vm, 'nowDuration', d);

			// console.log('--------------START---------------')
			// console.log('录音时长(秒)', params.duration);
			// console.log('录音大小(字节)', params.fileSize);
			// console.log('录音音量百分比(%)', params.vol);
			// console.log('当前录音的总数据([DataView, DataView...])', params.data);
			// console.log('--------------END---------------')
		};

		//this.startCanvas();
	},
	methods: {
		showPicker() {
			this.isShow = true;
			this.getPermission();
			this.$emit('show');
		},
		ontap(e) {
			if (this.beginRecoding) {
				this.touchend(e);
			} else {
				this.touchstart(e);
			}
		},
		// 获取麦克风权限
		getPermission() {
			let that = this;
			Recorder.getPermission().then(
				() => {
					console.log('录音给权限了');
				},
				(error) => {
					that.$msg('获取麦克风权限失败');
					console.log(`${error.name} : ${error.message}`);
				}
			);
		},
		// 波浪图canvas 配置
		startCanvas() {
			//录音波浪
			this.waveCanvas = document.getElementById('canvas');
			this.waveCanvas.width = 145;
			this.waveCanvas.height = 44;
			this.ctx = this.waveCanvas.getContext('2d');
		},
		// 手指开始触发
		touchstart(e) {
			this.blackBoxSpeak = true;
			this.startY = e.clientY;

			this.timeOutEvent = 0;
			// 长按1000毫秒后执行
			this.timeOutEvent = setTimeout(() => {
				this.startRecorder();
				this.beginRecoding = true;
			}, 500);
			return false;
		},
		toclose() {
			this.$emit('closeAudio2');
		},
		touchend2() {
			this.$emit('closeAudio', this.recorder.getWAVBlob(), this.nowDuration);
			this.nowDuration = '0:00';
		},
		// 手指离开屏幕触发
		touchend() {
			// 清空定时器
			clearTimeout(this.timeOutEvent);
			if (this.timeOutEvent !== 0) {
				this.beginRecoding = false;
				this.stopRecorder(); // 停止录音
				// 长按结束调用保存录音或者返回录音数据
				if (this.blackBoxSpeak) {
					// 未上滑取消
					// this.$emit('closeAudio', this.recorder.getWAVBlob())
				}
				//console.log('松开>>>', this.getRecorder())
				// this.nowDuration = null;
				this.drawColuList = [];
			}
		},
		// 滑动触发
		touchmove(e) {
			const endY = e.clientY;
			this.blackBoxSpeak = this.startY < endY;
		},
		//长按超过x毫秒-- 开始录音
		startRecorder() {
			this.recorder.start().then(
				() => {
					this.beginRecoding = true;
					//this.drawRecordWave();//开始绘制
					this.drawRecordColu(); // 开始绘制
				},
				(error) => {
					console.log(`${error.name} : ${error.message}`);
				}
			);
		},
		// 继续录音
		resumeRecorder() {
			this.recorder.resume();
		},
		// 暂停录音
		pauseRecorder() {
			this.recorder.pause();
			this.drawRecordId && cancelAnimationFrame(this.drawRecordId);
			this.drawRecordId = null;
		},
		// 结束录音
		stopRecorder() {
			this.recorder.stop();
			this.drawRecordId && cancelAnimationFrame(this.drawRecordId);
			this.drawRecordId = null;
		},
		// 录音播放
		playRecorder() {
			this.recorder.play();
			//this.drawPlay();//绘制波浪图
		},
		// 暂停录音播放
		pausePlayRecorder() {
			this.recorder.pausePlay();
		},
		// 恢复录音播放
		resumePlayRecorder() {
			this.recorder.resumePlay();
			//this.drawPlay();//绘制波浪图
		},
		// 停止录音播放
		stopPlayRecorder() {
			this.recorder.stopPlay();
		},
		// 销毁录音
		destroyRecorder() {
			const vm = this;
			if (vm.recorder) {
				vm.recorder.destroy().then(function () {
					vm.recorder = null;
					vm.drawRecordId && cancelAnimationFrame(vm.drawRecordId);
					vm.drawRecordId = null;
				});
			}
		},
		// 获取录音文件
		getRecorder() {
			let map = new Map();
			map.set('duration', this.recorder.duration); //录音总时长
			map.set('fileSize', this.recorder.fileSize); //录音总大小
			// map.set('filename', this.getNowTime() + '.wav');//录音总大小
			//录音结束，获取取录音数据
			map.set('PCMBlob', this.recorder.getPCMBlob()); //获取 PCM 数据
			map.set('wavBlob', this.recorder.getWAVBlob()); //获取 WAV 数据
			map.set('channel', this.recorder.getChannelData()); //获取左声道和右声道音频数据
			return map;
		},
		getNowTime() {
			let now = new Date();
			let year = now.getFullYear(); //获取完整的年份(4位,1970-????)
			let month = now.getMonth() + 1; //获取当前月份(0-11,0代表1月)
			let today = now.getDate(); //获取当前日(1-31)
			let hour = now.getHours(); //获取当前小时数(0-23)
			let minute = now.getMinutes(); //获取当前分钟数(0-59)
			let second = now.getSeconds(); //获取当前秒数(0-59)
			let nowTime = '';
			nowTime = year + '-' + this.fillZero(month) + '-' + this.fillZero(today) + ' ' + this.fillZero(hour) + ':' + this.fillZero(minute) + ':' + this.fillZero(second);
			return nowTime;
		},
		fillZero(str) {
			var realNum;
			if (str < 10) {
				realNum = '0' + str;
			} else {
				realNum = str;
			}
			return realNum;
		},
		// 下载pcm格式
		downPCM() {
			this.recorder.downloadPCM('新文件'); //这里传参进去的时文件名
		},
		// 下载wav格式
		downWAV() {
			this.recorder.downloadWAV('新文件'); //这里传参进去的时文件名
		},
		// 录音绘制波浪图
		drawRecordWave() {
			// 用requestAnimationFrame稳定60fps绘制
			this.drawRecordId = requestAnimationFrame(this.drawRecordWave);
			// 实时获取音频大小数据
			let dataArray = this.recorder.getRecordAnalyseData();
			//console.log('>>>',dataArray)
			let bufferLength = dataArray.length;

			// 填充背景色
			this.ctx.fillStyle = 'rgb(0,0,0)';
			this.ctx.fillRect(0, 0, this.waveCanvas.width, this.waveCanvas.height);

			// 设定波形绘制颜色
			this.ctx.lineWidth = 2;
			this.ctx.strokeStyle = 'rgb(109, 212, 0)';

			this.ctx.beginPath();
			let sliceWidth = (this.waveCanvas.width * 1.0) / bufferLength; // 一个点占多少位置，共有bufferLength个点要绘制
			let x = 0; // 绘制点的x轴位置
			for (var i = 0; i < bufferLength; i++) {
				var v = dataArray[i] / 128.0;
				var y = (v * this.waveCanvas.height) / 2;
				if (i === 0) {
					// 第一个点
					this.ctx.moveTo(x, y);
				} else {
					// 剩余的点
					this.ctx.lineTo(x, y);
				}
				// 依次平移，绘制所有点
				x += sliceWidth;
			}

			this.ctx.lineTo(this.waveCanvas.width, this.waveCanvas.height / 2);
			this.ctx.stroke();
		},
		// 录音绘制柱状图
		drawRecordColu() {
			// 用requestAnimationFrame稳定60fps绘制(官方写法，录音过程中，会一直自我调用，因此能得到持续的数据，然后根据数据绘制音波图)
			this.drawRecordId = requestAnimationFrame(this.drawRecordColu);
			// 实时获取音频大小数据
			let dataArray = this.recorder.getRecordAnalyseData();
			let transit = [];
			this.splitArr([...dataArray], transit);

			let rstArr = [];
			for (let i = 0; i < transit.length; i++) {
				rstArr.push(Math.max(...transit[i]));
			}
			this.drawColuList = [];
			for (var i = 0; i < rstArr.length; i++) {
				// var v = rstArr[i] / 128.0;
				// var h = v * this.waveCanvas.height / 3;
				// this.drawColuList.push(h)
				// 根据数值大小，设置音波柱状的高度
				let newDb = rstArr[i];
				let waveH = 10;
				if (newDb >= 128 && newDb <= 140) {
					waveH = 15;
				} else if (newDb >= 141 && newDb <= 160) {
					waveH = 20;
				} else if (newDb >= 161 && newDb <= 180) {
					waveH = 25;
				} else if (newDb >= 181 && newDb <= 200) {
					waveH = 30;
				} else if (newDb > 200) {
					waveH = 35;
				}
				this.drawColuList.push(waveH);
			}
			// console.log(this.drawColuList)
			this.$forceUpdate();
		},
		// 拆分数组
		splitArr(arr, rst, idx) {
			if (!arr || arr.length === 0) {
				return;
			}
			rst.push(arr.splice(0, idx ? idx : 32));
			this.splitArr(arr, rst);
		},
		// 取数组平均数
		arrAverageNum2(arr) {
			// let sum = eval(arr.join('+'));
			// return ~~((sum / arr.length) * 100) / 100;
			return;
		},
		// 关闭组件
		close() {
			this.$emit('closeAudio');
		},
		// 销毁实例
		beforeDestroy() {
			this.destroyRecorder();
		}
	}
};
</script>
<style scoped lang="scss">
.audio-enter {
	position: fixed;
	bottom: 0;
	height: 100%;
	width: 100%;
	z-index: 999999999;
	background-color: #ffffff;

	.custom-overlay {
		// background-color: rgba(0, 0, 0, 0.8);
	}

	.audio-pie {
		z-index: 999;
		position: absolute;
		left: 0;
		right: 0;
		bottom: 74px;
		text-align: center;

		.audio-pie_txt {
			height: 20px;
			font-size: 14px;
			font-family: PingFangSC-Regular, PingFang SC;
			font-weight: 400;
			color: #000000;
			line-height: 20px;
			margin-top: 20px;
		}

		.audio-pie_audio--times {
			height: 20px;
			font-size: 14px;
			font-family: PingFangSC-Regular, PingFang SC;
			font-weight: 400;
			color: #000000;
			line-height: 20px;
		}
		.audio-pie_audio--osc {
			width: 157px;
			height: 44px;
			//      background: #6DD400;
			margin: 24px auto 0;
			display: flex;
			align-items: center;

			.audio-pie_audio--osc_item {
				width: 2px;
				background-color: rgba(109, 212, 0, 1);
				border-radius: 1000px;

				&:not(:first-child) {
					margin-left: 3px;
				}
			}
		}
		.audio-pie_btn {
			margin-top: 60px;

			.audio-pie_btn-icon {
				position: relative;
				width: 60px;
				height: 60px;
				background: #6dd400;
				border-radius: 100%;
				margin: 0 auto;

				.audio-pie_btn-icon1 {
					position: absolute;
					top: 12px;
					left: 0;
					right: 0;
					margin: 0 auto;
					width: 36px;
					height: 36px;
					border: 4px solid #fff;
					border-radius: 100%;
				}
				.audio-pie_btn-icon2 {
					position: absolute;
					top: 22px;
					left: 0;
					right: 0;
					margin: 0 auto;
					width: 16px;
					height: 16px;
					background-color: #fff;
					border-radius: 100%;
				}

				.iconfont {
					color: #ffffff;
					font-size: 35px;
					line-height: 60px;
				}
			}
		}
	}
}

.lyview {
	height: 540upx;
	width: 100%;
	position: fixed;
	left: 0;
	bottom: 0;
	background-color: #ffffff;
	padding: 0 20upx;
	border-radius: 30upx 30upx 0 0;
	.lyviewTop {
		display: flex;
		align-items: center;
		padding: 20upx 40upx;
		font-size: 14px;

		.lyviewTopLeft {
			flex: 1;
			text-align: left;
			color: #666666;
		}

		.lyviewTopRight {
			flex: 1;
			text-align: right;
			color: #1c70ef;
		}
	}

	.lyviewCenter {
		padding: 54upx 0;
		text-align: center;

		.lyviewCenterTop {
			image {
				position: relative;
				margin: 0 auto;
				// left: 270upx;
				width: 172upx;
				height: 172upx;
			}
		}

		.lyviewCenterCenter {
			font-size: 16px;
			padding: 20upx 0 15upx 0;
			color: #333333;
		}

		.lyviewCenterBottom {
			font-size: 16px;
			padding: 10upx 0 15upx 0;
			color: #333333;
		}
	}
}
</style>
